package com.youth.routercore

import android.content.Intent
import android.os.Bundle
import androidx.core.os.bundleOf
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.*

object Router {
    private val scope by lazy { MainScope() }
    private val EMPTY_LAMBDA: (Intent) -> Unit = {}

    fun path(path: String?): RouterPathRequest {
        val scheme=path?:""
        "scheme=$scheme".logw("Router")

        val realScheme = parseScheme(scheme)
        "realScheme=$realScheme".logw("Router")
        return RouterCore.queryRouterPath(realScheme).apply {
            val params = parseSchemeParams(scheme)
            "scheme className=${this.className}".logw("Router")
            bundle.putAll(bundleOf(*params))
        }
    }

    fun RouterPathRequest.params(vararg pair: Pair<String, Any?>): RouterPathRequest {
        return apply {
            bundle.putAll(bundleOf(*pair))
        }
    }

    fun RouterPathRequest.params(data: Bundle?): RouterPathRequest {
        return apply {
            if (data != null)
                bundle.putAll(data)
        }
    }

    fun RouterPathRequest.skipInterceptor(): RouterPathRequest {
        return copy(needIntercept = false)
    }

    private fun RouterPathRequest.flowAction(
        needResult: Boolean = true
    ): Flow<Result<Intent>> {
        return RouterCore.dispatchRouterPath(this, needResult)
    }


    fun RouterPathRequest.launch(
        onError: (Throwable) -> Unit = {},
        cScope: CoroutineScope? = null,
        onResult: (Intent) -> Unit = EMPTY_LAMBDA,
    ) {
        val scope = cScope ?: scope
        if (onResult == EMPTY_LAMBDA) {
            flowAction(false).launchIn(scope)
        } else {
            flowAction(true).onEach {
                if (it.isSuccess) {
                    onResult(it.getOrDefault(Intent()))
                } else {
                    onError(it.exceptionOrNull() ?: Throwable())
                }
            }.launchIn(scope)
        }
    }

    val Router_Service_LAMBDA: (String, Class<*>) -> Any? = { identity, cls ->
        val real = identity.ifEmpty { cls.simpleName }
        var request = RouterCore.queryRouterService(real)
        if (request.className.isEmpty()) {
            request = request.copy(className = cls.name)
        }
        RouterCore.dispatchRouterService(request)
    }

    inline fun <reified T> routerService(
        identity: String = "",
        noinline func: (String, Class<*>) -> Any? = Router_Service_LAMBDA
    ): T? {
        return func(identity, T::class.java) as? T?
    }
}